package web

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
	"log"
	"net/http"
	"time"
)

// 自定义http配置
func StartWeb6() {
	//router := gin.Default()
	//http.ListenAndServe(":8080", router)

	//或者

	r := gin.Default()
	s := &http.Server{
		Addr:           ":8080",
		Handler:        r,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	s.ListenAndServe()
}

// 自定义验证器
// Booking 包含绑定和验证的数据。bingding属性绑定校验
type Booking struct {
	CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn,bookabledate" time_format:"2006-01-02"`
}

var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
	date, ok := fl.Field().Interface().(time.Time)
	if ok {
		today := time.Now()
		if today.After(date) {
			return false
		}
	}
	return true
}

func StartWeb8() {
	r := gin.Default()
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		//注册校验
		v.RegisterValidation("bookabledate", bookableDate)
	}
	r.GET("/bookable", getBookable)
	r.Run(":8085")
}

func getBookable(c *gin.Context) {
	var b Booking
	if err := c.ShouldBindWith(&b, binding.Query); err == nil {
		c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	}
}

// 自定义中间件
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		t := time.Now()
		//设置example变量
		c.Set("example", "12345")
		//请求前
		c.Next()
		//请求后
		latecy := time.Since(t)
		log.Print(latecy)

		//获取发送的status
		status := c.Writer.Status()
		log.Println(status)
	}
}

/*
*
gin.new()和gin.Default()的区别？
gin.New() 方法返回一个没有任何默认中间件的 Gin 引擎实例
gin.Default() 方法返回一个已经包含了一些默认中间件的 Gin 引擎实例。这些默认中间件包括 Logger 和 Recovery
Logger 中间件在请求开始时记录请求信息，并在请求结束时记录响应信息。Recovery 中间件则会在发生 panic 时恢复并输出堆栈跟踪信息，防止应用崩溃。
*/
func StartWeb9() {
	r := gin.New()
	//自定义中间件
	r.Use(Logger())
	r.GET("/test", func(c *gin.Context) {
		example := c.MustGet("example").(string)

		// 打印："12345"
		log.Println(example)
	})

	// 监听并在 0.0.0.0:8080 上启动服务
	r.Run(":8080")
}
